package io.jee.runshan.controller;

import io.jee.runshan.domain.remote.Article;
import io.jee.runshan.domain.remote.InputMessage;
import io.jee.runshan.domain.remote.MsgType;
import io.jee.runshan.domain.remote.OutputImageTextMessage;
import io.jee.runshan.domain.remote.OutputMessage;
import io.jee.runshan.domain.remote.OutputTextMessage;
import io.jee.runshan.utils.SHACoder;

import java.io.Writer;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;

@Controller
@RequestMapping("/weixin/")
public class WeixinReceiver {
	private static final String Token = "siweibei";

	@RequestMapping("receive")
	public void receive(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		response.setCharacterEncoding("UTF-8");
		response.setContentType("application/xml");
		// 微信服务器将发送GET请求到填写的URL上,这里需要判定是否为GET请求
		boolean isGet = request.getMethod().toLowerCase().equals("get");
		System.out.println("获得微信请求:" + request.getMethod() + " 方式");
		if (isGet) {
			// 验证URL真实性
			String signature = request.getParameter("signature");// 微信加密签名
			String timestamp = request.getParameter("timestamp");// 时间戳
			String nonce = request.getParameter("nonce");// 随机数
			String echostr = request.getParameter("echostr");// 随机字符串
			List<String> params = new ArrayList<String>();
			params.add(Token);
			params.add(timestamp);
			params.add(nonce);
			// 1. 将token、timestamp、nonce三个参数进行字典序排序
			Collections.sort(params, new Comparator<String>() {
				@Override
				public int compare(String o1, String o2) {
					return o1.compareTo(o2);
				}
			});
			// 2. 将三个参数字符串拼接成一个字符串进行sha1加密
			String temp = SHACoder.encode(params.get(0) + params.get(1)
					+ params.get(2));
			if (temp.equals(signature)) {
				response.getWriter().write(echostr);
			}
		} else {
			try {
				// 处理接收消息
				ServletInputStream in = request.getInputStream();
				// 将POST流转换为XStream对象
				XStream xs = new XStream(new DomDriver());
				// 将指定节点下的xml节点数据映射为对象
				xs.alias("xml", InputMessage.class);
				// 将流转换为字符串
				StringBuilder xmlMsg = new StringBuilder();
				byte[] b = new byte[4096];
				for (int n; (n = in.read(b)) != -1;) {
					xmlMsg.append(new String(b, 0, n, "UTF-8"));
				}
				// 将xml内容转换为InputMessage对象
				InputMessage inputMsg = (InputMessage) xs.fromXML(xmlMsg
						.toString());
				// 取得消息类型
				String msgType = inputMsg.getMsgType();
				// 根据消息类型获取对应的消息内容
				// 根据消息类型获取对应的消息内容
				if (msgType.equals(MsgType.Text.toString())) {
					// 文本消息
					System.out.println("开发者微信号：" + inputMsg.getToUserName());
					System.out.println("发送方帐号：" + inputMsg.getFromUserName());
					System.out.println("消息创建时间：" + inputMsg.getCreateTime());
					System.out.println("消息内容：" + inputMsg.getContent());
					System.out.println("消息Id：" + inputMsg.getMsgId());

					XStream xstream = new XStream(new XppDriver() {
						@Override
						public HierarchicalStreamWriter createWriter(Writer out) {
							return new PrettyPrintWriter(out) {
								@Override
								protected void writeText(QuickWriter writer,
										String text) {
									if (!text.startsWith("<![CDATA[")) {
										text = "<![CDATA[" + text + "]]>";
									}
									writer.write(text);
								}
							};
						}
					});

					if (inputMsg.getContent().equals("0")) {
						OutputTextMessage outputMsg = new OutputTextMessage();
						outputMsg.setContent("你的消息已经收到，谢谢！");
						setOutputMsgInfo(outputMsg, inputMsg);
						xstream.alias("xml", outputMsg.getClass());
						String xml = xstream.toXML(outputMsg);
						response.getWriter().write(xml);
					} else if (inputMsg.getContent().equals("1")) {
						OutputImageTextMessage outputMsg = new OutputImageTextMessage();
						List<Article> list = new ArrayList<Article>();
						for (int i = 0; i < 2; i++) {
							Article article = new Article();
							article.setDescription("图文信息描述：" + (i + 1));
							article.setTitle("标题：" + (i + 1));
							article.setPicUrl("http://img5.imgtn.bdimg.com/it/u=2785102442,2931277015&fm=21&gp=0.jpg");
							article.setUrl("http://blog.csdn.net/lyq8479");
							list.add(article);
						}
						outputMsg.setArticleCount(list.size());
						outputMsg.setArticles(list);
						setOutputMsgInfo(outputMsg, inputMsg);
						xstream.processAnnotations(Article.class);
						xstream.alias("xml", outputMsg.getClass());
						String xml = xstream.toXML(outputMsg);
						response.getWriter().write(xml);
					}
				}
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
	}

	// 设置详细信息
	private void setOutputMsgInfo(OutputMessage oms, InputMessage msg)
			throws Exception {
		Class<?> outMsg = oms.getClass().getSuperclass();
		Field CreateTime = outMsg.getDeclaredField("CreateTime");
		Field ToUserName = outMsg.getDeclaredField("ToUserName");
		Field FromUserName = outMsg.getDeclaredField("FromUserName");

		ToUserName.setAccessible(true);
		CreateTime.setAccessible(true);
		FromUserName.setAccessible(true);

		CreateTime.set(oms, new Date().getTime());
		ToUserName.set(oms, msg.getFromUserName());
		FromUserName.set(oms, msg.getToUserName());
	}
}
